#include "MovingCameraGUI.hpp"
#include "../Renderer/Renderer.hpp"

namespace zzz {

MovingCameraGUI::MovingCameraGUI()
:moving_speed_(1), accelerate_time_(2.0) {}

bool MovingCameraGUI::OnLButtonDown(unsigned int nFlags,int x,int y) {
  renderer_->GetContext()->OwnMouse(true);
  last_x_ = x;
  last_y_ = y;
  return true;
}

bool MovingCameraGUI::OnMouseMove(unsigned int nFlags,int x,int y) {
  if (CheckBit(nFlags, ZZZFLAG_LMOUSE)) {
    ChangeYaw(0.01*(x - last_x_));
    ChangePitch(0.01*(y - last_y_));
    last_x_ = x;
    last_y_ = y;
    return true;
  }
  return false;
}

bool MovingCameraGUI::OnMouseWheel(unsigned int nFlags, int zDelta, int x,int y) {
  int nstep=zDelta;
  int i;
  if (nstep<0) {
    nstep=-nstep;
    for (i=0; i<nstep; i++) MoveForwards(moving_speed_);
  } else {
    for (i=0; i<nstep; i++) MoveForwards(-moving_speed_);
  }
  return true;
}

bool MovingCameraGUI::OnMButtonDown(unsigned int nFlags,int x,int y) {
  return false;  // just override CameraGUI
}

bool MovingCameraGUI::OnMButtonUp(unsigned int nFlags,int x,int y) {
  return false;  // just override CameraGUI
}

bool MovingCameraGUI::OnChar(unsigned int nChar, unsigned int nRepCnt, unsigned int nFlags) {
  switch(nChar)
  {
  case ZZZKEY_w:
    UpdateSpeed();
    MoveForwards(current_speed_);
    return true;
  case ZZZKEY_s:
    UpdateSpeed();
    MoveForwards(-current_speed_);
    return true;
  case ZZZKEY_a:
    UpdateSpeed();
    MoveLeftwards(current_speed_);
    return true;
  case ZZZKEY_d:
    UpdateSpeed();
    MoveLeftwards(-current_speed_);
    return true;
  case ZZZKEY_q:
    UpdateSpeed();
    MoveUpwards(current_speed_);
    return true;
  case ZZZKEY_e:
    UpdateSpeed();
    MoveUpwards(-current_speed_);
    return true;
  case ZZZKEY_MINUS:
    moving_speed_ *= 0.8;
    return true;
  case ZZZKEY_EQUAL:
    moving_speed_ /= 0.8;
    return true;
  }
  return false;
}

void MovingCameraGUI::UpdateSpeed() {
  double elapsed = timer_.Elapsed();
  // If just started, change speed to 1/20 moving_speed_;
  if (elapsed > 0.2) {
    current_speed_ = moving_speed_ / 20.0;
    timer_.Restart();
    return;
  } else {
    // Accelerate from 0 to moving_speed_ in 2 secs.
    if (current_speed_ != moving_speed_)  {
      current_speed_ += current_speed_ /accelerate_time_ * elapsed;
      if (current_speed_ > moving_speed_) current_speed_ = moving_speed_;
    }
    timer_.Restart();
  }
}

}  // namespace zzz